package cn.tedu.lucky.draw.server.aspect;

import cn.tedu.lucky.draw.server.common.annotation.OperationLog;
import cn.tedu.lucky.draw.server.protrocol.po.UserLog;
import cn.tedu.lucky.draw.server.service.IUserLogService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.time.LocalDateTime;

@Component
@Aspect
public class LogAspect {

    @Autowired
    private IUserLogService userLogService;

    @Pointcut("@annotation(cn.tedu.lucky.draw.server.common.annotation.OperationLog)")
    public void doLog(){

    }

    @Around("doLog()")
    public Object doLogAround(ProceedingJoinPoint joinPoint) throws Throwable{
        int status=1;//初始状态
        String error=null;//错误信息
        long time=0l;//耗时
        long t1 = System.currentTimeMillis();
        try{
            Object proceed = joinPoint.proceed();
            long t2 = System.currentTimeMillis();
            time=t2-t1;
            return proceed;
        }catch (Throwable throwable){
            status = 0;//表示出现错误了
            error = throwable.getMessage();
            long t3 = System.currentTimeMillis();
            time=t3-t1;
            throw throwable;
        }finally {
            saveOperationLog(joinPoint,time,status,error);
        }

    }

    private void saveOperationLog(ProceedingJoinPoint joinPoint, long time, int status, String error) throws NoSuchMethodException, JsonProcessingException {
        //获取用户行为日志
        //1.获取用户IP地址
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        String ip = request.getRemoteAddr();
        //获取登陆用户
        String username="tedu";
        //获取类的字节码文件
        Class<?> targetCls = joinPoint.getTarget().getClass();
        MethodSignature ms = (MethodSignature) joinPoint.getSignature();

        Method targetMethod = targetCls.getDeclaredMethod(
                ms.getName(),
                ms.getParameterTypes()
        );
        //获取方法上的注解
        OperationLog annotation = targetMethod.getAnnotation(OperationLog.class);
        //获取操作名称
        String operation = annotation.operation();
        //获取目标的方法名称
        String method = targetCls.getName() + "." + targetMethod.getName();

        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.registerModule(new JavaTimeModule());
        String params = objectMapper.writeValueAsString(joinPoint.getArgs());

        //封装用户行为日志
        UserLog userLog = new UserLog(
               null, username,ip,operation,method,params,time, LocalDateTime.now(),status,error
        );
        userLogService.save(userLog);
    }
}
